package ucron

import (
    "reflect"
    "fmt"
    "github.com/jakecoffman/cron"
)

/**
 @Description：获取struct的全名
 @Param:
 @Return：
 */
func getFullName(typ reflect.Type) string {
    return typ.PkgPath() + "." + typ.Name()
}

/**
 @Description：获取job的名字
 @Param:
 @Return：
 */
func getJobName(val reflect.Value) string {
    if fun := val.MethodByName("JobName"); fun.IsValid() {
        vals := fun.Call([]reflect.Value{})
        if len(vals) > 0 && vals[0].Kind() == reflect.String {
            return vals[0].String()
        }
    }

    return reflect.Indirect(val).Type().Name()
}

/**
 @Description：注册Job
 @Param:
 @Return：
 */
func RegisterCronJob(job cron.Job)  {
    val := reflect.ValueOf(job)
    typ := reflect.Indirect(val).Type()

    // 输入必须为ptr
    if val.Kind() != reflect.Ptr {
        panic(fmt.Errorf("<crontask.registerCronJob> cannot use non-ptr job struct `%s`", getFullName(typ)))
    }

    // 输入为指针的指针
    if typ.Kind() == reflect.Ptr {
        panic(fmt.Errorf("<crontask.registerCronJob> only allow ptr model struct, `%s`", typ))
    }

    // jobName，job的直接名字，非全名
    jobName := getJobName(val)
    // name: 全名，包括pkg的名字
    name := getFullName(typ)

    if _, exist := jobCache.getByFullName(name); exist {
        panic(fmt.Errorf("<crontask.registerCronJob> job `%s` repeat register, must be unique", name))
    }
    if _, exist := jobCache.get(jobName); exist {
        panic(fmt.Errorf("<crontask.registerCronJob> job name `%s` repeat register, must be unique", jobName))
    }

    jb := newJobInfo(val)
    jb.JobName = jobName
    jb.Job = job
    jobCache.set(jobName, jb)
    return
}

/**
 @Description：获取所有job名
 @Param:
 @Return：
 */
func GetAllJob() []string {
    return jobCache.allJobName()
}

/**
 @Description：根据名字获取job model模板
 @Param:
 @Return：
 */
func GetJob(name string) (*JobModel, bool) {
    jm, exist := jobCache.get(name)
    return jm, exist
}
